package com.mjk.manager.api.interceptor;

import com.google.common.util.concurrent.RateLimiter;
import com.google.gson.JsonParser;
import com.mjk.common.base.response.BeeResponse;
import com.mjk.common.core.jdbc.service.plus.idbservice.BeeDBService;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.interceptor.InterceptorChain;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.util.MapUtils;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.web.getway.constns.GetWayError;
import com.mjk.common.web.getway.constns.GetwayConsts;
import com.mjk.common.web.getway.restful.interceptor.GetWayInterceptorReq;
import com.mjk.common.web.getway.restful.interceptor.annotation.BeeGetWayInterceptor;
import com.mjk.common.web.getway.restful.interceptor.type.GetWayInterceptor;
import com.mjk.common.web.getway.restful.interceptor.type.GetWayInterceptorType;
import com.mjk.manager.api.model.ApiModel;
import com.mjk.manager.api.model.ApiParamsConver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 出入参数转化 ，数据来源于redis
 * @author mjk
 *
 */
@BeeGetWayInterceptor(value=-998,interceptorType={GetWayInterceptorType.COMMON})
public class ApiParamsConverInterceptor implements GetWayInterceptor, BeeApplicationListener {
	
	public  String TIME_OUT = "timeOut";
	
	public  String DEFAULT_TIME_OUT = "15";
	
	@SuppressWarnings("rawtypes")
	@Autowired
	private BeeDBService beeDBService;
	
	public final Map<String, ApiParamsConver> maps = new HashMap<>();
	
	//所有配置beeapi的 限流器信息
	public static final Map<String ,RateLimiter> rateMap = new ConcurrentHashMap<>();
	//所有的超时信息
	public static final Map<String ,Integer> timeOutMap = new ConcurrentHashMap<>();
	
	@Override
	public BeeResponse interceptor(GetWayInterceptorReq request,
								   InterceptorChain<GetWayInterceptorReq, BeeResponse> next) {
		String instans = MapUtils.getString(request.getRestfulParams(), GetwayConsts.INSTANCE);
		String method = MapUtils.getString(request.getParams(), GetwayConsts.METHOD);
		String versionkey = MapUtils.getString(request.getRestfulParams(), GetwayConsts.VERSION);
		
		RateLimiter limiter = rateMap.get(instans+method);
		if(ObjectUtils.isNotEmpty(limiter)){
			if(!limiter.tryAcquire()){
				return GetWayError.QPS_MORETHAN.tranceError("");
			}
		}
		//设置超时
		Integer timeout = timeOutMap.get(instans+method);				
		//如果设置了超时时间，使用设置的时间
		if(ObjectUtils.isNotEmpty(timeout)){					
			request.getParams().put(TIME_OUT, timeout.toString());					
		}			
		
		Map<String,Object> params = request.getParams();
		ApiParamsConver conver = null;
		if(ObjectUtils.isNotEmpty(versionkey)){
			conver = maps.get(versionkey+instans+method);
			if(ObjectUtils.isNotEmpty(conver)){
				//转化入参
				if(ObjectUtils.isNotEmpty(conver.getInParams())&& GsonUtils.isJson(conver.getInParams())){
					Map<String,String> convers = GsonUtils.gson2Map(conver.getInParams());
					for(Entry<String,String> entry : convers.entrySet()){
						if(params.containsKey(entry.getKey())){
							params.put(entry.getValue(), params.remove(entry.getKey()));
						}
					}
					//转化json体里面的数据
					params.computeIfAbsent(GetwayConsts.PARAMS_BODY, k -> GsonUtils.replaceKey(k, convers));
//					if(params.containsKey(GetwayConsts.PARAMS_BODY)){
//						String json = MapUtils.getString(params, GetwayConsts.PARAMS_BODY);
//						params.put(GetwayConsts.PARAMS_BODY, GsonUtils.bean2Json(GsonUtils.replaceKey(new JsonParser().parseString(json), convers)));
//					}
				}
			}
		}		
		BeeResponse result = next.proceed(request);
		if(null!=conver&&ObjectUtils.isNotEmpty(conver.getOutParams())){
			Map<String,String> convers = GsonUtils.gson2Map(conver.getOutParams());
			if(!CollectionUtils.isEmpty(convers) && ObjectUtils.isNotEmpty(result.getData())) {
				if(result.getData() instanceof String) {
					if(GsonUtils.isJson(result.getData().toString())) {
						result.setData(GsonUtils.replaceKey(result.getData().toString(), convers));
					}
				}else {
					String json = GsonUtils.bean2Json(result.getData());
					result.setData(GsonUtils.replaceKey(json, convers));
				}
			}
			//ResponseUtils.returnGetWay(request.getResponse(), result,convers);
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void doApplicationEvent(ContextRefreshedEvent event) {
		BeeQueryWrapper wrapper = new BeeQueryWrapper(new ApiModel());
        List<ApiModel> models = beeDBService.findManyByWrapper(wrapper);

		BeeQueryWrapper converWrapper = new BeeQueryWrapper(new ApiParamsConver());
        List<ApiParamsConver> convers = beeDBService.findManyByWrapper(converWrapper);
		Map<Integer,List<ApiParamsConver>> converMap =convers.stream().collect(Collectors.groupingBy(ApiParamsConver::getId));
		if(!CollectionUtils.isEmpty(models)){
			for(ApiModel model : models){
				if(converMap.containsKey(model.getId())){
					for(ApiParamsConver conver : converMap.get(model.getId())){
						maps.put(conver.getMappingVersion()+model.getApiWork()+model.getApiMethod(), conver);
					}
				}
				if(ObjectUtils.isNotEmpty(model.getLimterNum()) && model.getLimterNum()>0){
					RateLimiter  limiter = RateLimiter.create(model.getLimterNum());
					rateMap.put(model.getApiWork()+model.getApiMethod(), limiter);
				}
				if(ObjectUtils.isNotEmpty(model.getTimeOut()) &&model.getTimeOut()>0){
					timeOutMap.put(model.getApiWork()+model.getApiMethod(), model.getTimeOut());
				}
			}
		}
	}
}
